{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Разбор резюме\n",
    "\n",
    "Рекрутерам и рекрутерским агенствам присылают резюме в формате pdf и docx. Чтобы вести базу кандидатов, из текстов нужно извлекать имя, возраст, контакты соискателя, предыдущий опыт, желаемую зарплату.\n",
    "\n",
    "В этом примере рассматриваются только стандартные резюме, сгенерированные сайтом HH. Вариативность таких текстов очень низкая, всё оформлено строго по шаблону. С помощью Yargy-парсера можно написать программу, которая работает с произвольными резюме, но эта задача выходит за рамки данного примера.\n",
    "\n",
    "![](thumb.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from glob import glob\n",
    "\n",
    "texts = []\n",
    "for path in glob('texts/*.txt'):\n",
    "    with open(path) as file:\n",
    "        text = file.read()\n",
    "        texts.append(text)\n",
    "        \n",
    "intros = [_[:700] for _ in sorted(texts)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Женщина, 44 года, родилась 31 марта 1972\n",
      "\n",
      "Проживает: Смоленск\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "Не готова к переезду, не готова к командировкам\n",
      "\n",
      "Желаемая должность и зарплата\n",
      "Супервайзер отдела продаж\n",
      "Продажи\n",
      "\n",
      "• Розничная торговля\n",
      "• Торговые сети\n",
      "\n",
      "Занятость: полная занятость\n",
      "График работы: полный день\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "\n",
      "45 000\n",
      "руб.\n",
      "\n",
      "Опыт работы — 5 лет 2 месяца\n",
      "Июнь 2011 — Июль\n",
      "2016\n",
      "5 лет 2 месяца\n",
      "\n",
      "МинералТрансКомпани, ООО\n",
      "Смоленск, mikei.ru\n",
      "\n",
      "Директор по продажам\n",
      "Контроль планов продаж. Снижение потерь. Организация работы торговой точки. Обучение\n",
      "персонала. Открытие четырех новых магазинов с нуля.  Куст курирования 7-12 магазинов.\n",
      "\n",
      "Об\n",
      "------------------------------\n",
      "\n",
      "Женщина, 38 лет, родилась 11 ноября 1977\n",
      "\n",
      "Проживает: Санкт-Петербург, м. Купчино\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "Не готова к переезду, не готова к командировкам\n",
      "\n",
      "Желаемая должность и зарплата\n",
      "Главный  бухгалтер\n",
      "Бухгалтерия, управленческий учет, финансы предприятия\n",
      "\n",
      "• Бухгалтер\n",
      "• Аудит\n",
      "• Руководство бухгалтерией\n",
      "\n",
      "Занятость: полная занятость\n",
      "График работы: полный день\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "\n",
      "150 000\n",
      "руб.\n",
      "\n",
      "Опыт работы — 9 лет 5 месяцев\n",
      "Март 2015 —\n",
      "настоящее время\n",
      "1 год 7 месяцев\n",
      "\n",
      "сеть ресторанов\n",
      "Санкт-Петербург\n",
      "\n",
      "Главный  бухгалтер , аналитический , управленческий учет .\n",
      "Ведение бух/учета в полном объеме , управленческая отчетность для собст\n",
      "------------------------------\n",
      "\n",
      "Женщина, 29 лет, родилась 13 апреля 1987\n",
      "\n",
      "Проживает: Краснодар\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "Не готова к переезду, готова к редким командировкам\n",
      "\n",
      "Желаемая должность и зарплата\n",
      "Менеджер по транспортной логистике, Логист,\n",
      "Администратор, Офис-менеджер, Оператор ПК\n",
      "Начало карьеры, студенты\n",
      "\n",
      "• Транспорт, Логистика\n",
      "• Административный персонал\n",
      "• Туризм, Гостиницы, Рестораны\n",
      "\n",
      "Занятость: полная занятость\n",
      "График работы: полный день\n",
      "Желательное время в пути до работы: не более часа\n",
      "\n",
      "30 000\n",
      "руб.\n",
      "\n",
      "Опыт работы — 7 лет 8 месяцев\n",
      "Сентябрь 2013 —\n",
      "Январь 2016\n",
      "2 года 5 месяцев\n",
      "\n",
      "ООО \"Юг-Бизнеспартнер\"\n",
      "Краснодар, ugbp.ru\n",
      "\n",
      "Главный специалист управления закупок (инертные материалы,\n",
      "дорожн\n",
      "------------------------------\n"
     ]
    }
   ],
   "source": [
    "from random import seed, sample\n",
    "\n",
    "seed(41)\n",
    "for text in sample(intros, 3):\n",
    "    print(text)\n",
    "    print('---' * 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Grammar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "\n",
    "from ipymarkup import show_span_ascii_markup as show_markup\n",
    "\n",
    "from yargy import (\n",
    "    Parser,\n",
    "    rule, or_, and_, not_\n",
    ")\n",
    "from yargy.predicates import (\n",
    "    eq, in_,\n",
    "    type, normalized,\n",
    "    dictionary,\n",
    "    gte, lte\n",
    ")\n",
    "from yargy.pipelines import (\n",
    "    pipeline,\n",
    "    morph_pipeline\n",
    ")\n",
    "from yargy.interpretation import (\n",
    "    fact,\n",
    "    attribute\n",
    ")\n",
    "from yargy.tokenizer import MorphTokenizer, EOL\n",
    "\n",
    "\n",
    "Intro = fact(\n",
    "    'Intro',\n",
    "    ['gender', 'age', 'birth', 'location',\n",
    "     attribute('citizenship').repeatable(),\n",
    "     attribute('permission').repeatable(),\n",
    "     'relocation', 'travel',\n",
    "     'position',\n",
    "     attribute('subspecializations').repeatable(),\n",
    "     'employment', 'schedule', 'commute',\n",
    "     'salary'\n",
    "    ]\n",
    ")\n",
    "\n",
    "\n",
    "INT = type('INT')\n",
    "COMMA = eq(',')\n",
    "COLON = eq(':')\n",
    "\n",
    "\n",
    "def show_json(data):\n",
    "    print(json.dumps(data, indent=2, ensure_ascii=False))\n",
    "\n",
    "\n",
    "def show_matches(rule, *lines):\n",
    "    parser = Parser(rule)\n",
    "    for line in lines:\n",
    "        matches = parser.findall(line)\n",
    "        spans = [_.span for _ in matches]\n",
    "        show_markup(line, spans)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Gender"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "мужчина, Мужчина, мужчину\n",
      "         ───────         \n",
      "Женщина\n",
      "───────\n"
     ]
    }
   ],
   "source": [
    "GENDERS = {\n",
    "    'Женщина': 'female',\n",
    "    'Мужчина': 'male'\n",
    "}\n",
    "\n",
    "GENDER = in_(GENDERS).interpretation(\n",
    "    Intro.gender.custom(GENDERS.get)\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    GENDER,\n",
    "    'мужчина, Мужчина, мужчину',\n",
    "    'Женщина'\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Age"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "21 год, 25 лет\n",
      "──────  ──────\n"
     ]
    }
   ],
   "source": [
    "AGE = rule(\n",
    "    INT,\n",
    "    normalized('год')\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    AGE,\n",
    "    '21 год, 25 лет'\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Birth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "родился 21 февраля 1990\n",
      "───────────────────────\n",
      "родиться 32 сентябрь 2000\n",
      "родилась 01 июля 1917\n",
      "─────────────────────\n"
     ]
    }
   ],
   "source": [
    "Date = fact(\n",
    "    'Date',\n",
    "    ['year', 'month', 'day']\n",
    ")\n",
    "\n",
    "\n",
    "AGE = rule(\n",
    "    INT.interpretation(\n",
    "        Intro.age.custom(int)\n",
    "    ),\n",
    "    normalized('год')\n",
    ")\n",
    "\n",
    "MONTHS = {\n",
    "    'январь': 1,\n",
    "    'февраль': 2,\n",
    "    'март': 3,\n",
    "    'апрель': 4,\n",
    "    'май': 5,\n",
    "    'июнь': 6,\n",
    "    'июль': 7,\n",
    "    'август': 8,\n",
    "    'сентябрь': 9,\n",
    "    'октябрь': 10,\n",
    "    'ноябрь': 11,\n",
    "    'декабрь': 12\n",
    "}\n",
    "\n",
    "MONTH_NAME = dictionary(\n",
    "    MONTHS\n",
    ").interpretation(\n",
    "    Date.month.normalized().custom(MONTHS.get)\n",
    ")\n",
    "\n",
    "DAY = and_(\n",
    "    gte(1),\n",
    "    lte(31)\n",
    ").interpretation(\n",
    "    Date.day.custom(int)\n",
    ")\n",
    "\n",
    "YEAR = and_(\n",
    "    gte(1900),\n",
    "    lte(2100)\n",
    ").interpretation(\n",
    "    Date.year.custom(int)\n",
    ")\n",
    "\n",
    "DATE = rule(\n",
    "    DAY,\n",
    "    MONTH_NAME,\n",
    "    YEAR\n",
    ").interpretation(\n",
    "    Date\n",
    ")\n",
    "\n",
    "BIRTH = rule(\n",
    "    normalized('родиться'),\n",
    "    DATE.interpretation(\n",
    "        Intro.birth\n",
    "    )\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    BIRTH,\n",
    "    'родился 21 февраля 1990',\n",
    "    'родиться 32 сентябрь 2000',\n",
    "    'родилась 01 июля 1917',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Socdem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Мужчина, 24 года, родился 30 ноября 1991\n",
      "Женщина, 19 лет, родилась 30 мая 1997\n",
      "Женщина, 58 лет, родилась 5 января 1958\n",
      "Мужчина, 21 год, родился 18 октября 1994\n",
      "Мужчина, 25 лет, родился 15 ноября 1990\n",
      "Женщина, 18 лет, родилась 26 ноября 1997\n",
      "Женщина, 27 лет, родилась 5 сентября 1988\n",
      "Мужчина, 20 лет, родился 24 июля 1996\n",
      "Мужчина, 38 лет, родился 24 мая 1978\n",
      "Мужчина, 21 год, родился 8 июня 1995\n"
     ]
    }
   ],
   "source": [
    "SOCDEM = rule(\n",
    "    GENDER, COMMA,\n",
    "    AGE, COMMA,\n",
    "    BIRTH\n",
    ")\n",
    "\n",
    "\n",
    "parser = Parser(SOCDEM)\n",
    "seed(10)\n",
    "for text in sample(intros, 10):\n",
    "    for match in parser.findall(text):\n",
    "        start, stop = match.span\n",
    "        print(text[start:stop])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Location"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(['Проспект Мира',\n",
       "  'Алма-Атинская',\n",
       "  'Нахимовский проспект',\n",
       "  'Парк Победы',\n",
       "  'Проспект свободы',\n",
       "  'Академгородок',\n",
       "  'Достоевская',\n",
       "  'Окружная',\n",
       "  'Партизанская',\n",
       "  'Козья слобода'],\n",
       " ['Старонижестеблиевская',\n",
       "  'Голицыно',\n",
       "  'Атаманская',\n",
       "  'Перевальск',\n",
       "  'Обоянь',\n",
       "  'Кораблино',\n",
       "  'Биробиджан',\n",
       "  'Ижевск',\n",
       "  'Чаплыгин',\n",
       "  'Куйбышево'])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# https://api.hh.ru/metro\n",
    "# https://api.hh.ru/areas\n",
    "\n",
    "def load_lines(path):\n",
    "    with open(path) as file:\n",
    "        for line in file:\n",
    "            yield line.rstrip('\\n')\n",
    "            \n",
    "            \n",
    "METRO_STATIONS = set(load_lines('dicts/metro.txt'))\n",
    "AREAS = set(load_lines('dicts/areas.txt'))\n",
    "seed(10)\n",
    "sample(sorted(METRO_STATIONS), 10), sample(sorted(AREAS), 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "место проживания: Москва, м. Парк Победы\n",
      "                  ──────────────────────\n",
      "Киев, м.Киевская\n",
      "────────────────\n",
      "Россия\n",
      "──────\n",
      "в Москве\n",
      "м. парк победы\n",
      "на м. Кропоткинской\n"
     ]
    }
   ],
   "source": [
    "Location = fact(\n",
    "    'Location',\n",
    "    ['area', 'metro']\n",
    ")\n",
    "\n",
    "\n",
    "METRO = rule(\n",
    "    'м', '.',\n",
    "    pipeline(METRO_STATIONS).interpretation(\n",
    "        Location.metro\n",
    "    )\n",
    ")\n",
    "\n",
    "AREA = pipeline(AREAS).interpretation(\n",
    "    Location.area\n",
    ")\n",
    "\n",
    "LOCATION = rule(\n",
    "    AREA,\n",
    "    rule(\n",
    "        COMMA,\n",
    "        METRO\n",
    "    ).optional()\n",
    ").interpretation(\n",
    "    Location\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    LOCATION,\n",
    "    'место проживания: Москва, м. Парк Победы',\n",
    "    'Киев, м.Киевская',\n",
    "    'Россия',\n",
    "    'в Москве',\n",
    "    'м. парк победы',\n",
    "    'на м. Кропоткинской',\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Проживает: Москва, м. Новогиреево\n",
      "Проживает: Тула\n",
      "Проживает: Липецк\n",
      "Проживает: Зеленоград\n",
      "Проживает: Новосибирск, м. Золотая нива\n",
      "Проживает: Тамбов\n",
      "Проживает: Москва\n",
      "Проживает: Москва, м. Сухаревская\n",
      "Проживает: Энгельс\n",
      "Проживает: Казань, м. Проспект Победы\n"
     ]
    }
   ],
   "source": [
    "TITLE = rule(\n",
    "    normalized('проживает'), COLON\n",
    ")\n",
    "\n",
    "LIVES_AT = rule(\n",
    "    TITLE,\n",
    "    LOCATION\n",
    ")\n",
    "\n",
    "\n",
    "parser = Parser(LIVES_AT)\n",
    "seed(10)\n",
    "for text in sample(intros, 10):\n",
    "    for match in parser.findall(text):\n",
    "        start, stop = match.span\n",
    "        print(text[start:stop])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Citizenship"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Гражданство: Россия, Франция\n",
      "────────────────────────────\n",
      "Гражданство: Россия, Франция, Украина\n",
      "────────────────────────────         \n"
     ]
    }
   ],
   "source": [
    "TITLE = rule(\n",
    "    'Гражданство', COLON\n",
    ")\n",
    "\n",
    "ITEM = AREA.interpretation(\n",
    "    Intro.citizenship\n",
    ")\n",
    "\n",
    "LOCATIONS = rule(\n",
    "    ITEM,\n",
    "    rule(\n",
    "        COMMA,\n",
    "        ITEM\n",
    "    ).optional()\n",
    ")\n",
    "\n",
    "CITIZENSHIP = rule(\n",
    "    TITLE,\n",
    "    LOCATIONS\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    CITIZENSHIP,\n",
    "    'Гражданство: Россия, Франция',\n",
    "    'Гражданство: Россия, Франция, Украина',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Permission"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "есть разрешение на работу: Россия, Франция, Украина\n",
      "───────────────────────────────────────────────────\n",
      "есть разрешение на работу: Россия\n",
      "─────────────────────────────────\n"
     ]
    }
   ],
   "source": [
    "TITLE = pipeline([\n",
    "    'есть разрешение на работу:'\n",
    "])\n",
    "\n",
    "ITEM = AREA.interpretation(\n",
    "    Intro.permission\n",
    ")\n",
    "\n",
    "LOCATIONS = rule(\n",
    "    ITEM,\n",
    "    rule(\n",
    "        COMMA,\n",
    "        ITEM\n",
    "    ).optional().repeatable()\n",
    ")\n",
    "\n",
    "PERMISSION = rule(\n",
    "    TITLE,\n",
    "    LOCATIONS\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    PERMISSION,\n",
    "    'есть разрешение на работу: Россия, Франция, Украина',\n",
    "    'есть разрешение на работу: Россия',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Relocation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "готов к переезду\n",
      "────────────────\n",
      "не готова к переезду\n",
      "────────────────────\n",
      "готова к переезду: Россия, Украина, СНГ\n",
      "──────────────────────────────────     \n",
      "хочу переехать: Франция\n",
      "───────────────────────\n"
     ]
    }
   ],
   "source": [
    "Relocation = fact(\n",
    "    'Relocation',\n",
    "    ['ready', attribute('where').repeatable()]\n",
    ")\n",
    "\n",
    "TYPES = {\n",
    "    'готов к переезду': True,\n",
    "    'хочу переехать': True,\n",
    "    'не готов к переезду': False\n",
    "}\n",
    "\n",
    "IS_READY = morph_pipeline(TYPES).interpretation(\n",
    "    Relocation.ready.normalized().custom(TYPES.get)\n",
    ")\n",
    "\n",
    "ITEM = AREA.interpretation(\n",
    "    Relocation.where\n",
    ")\n",
    "\n",
    "LOCATIONS = rule(\n",
    "    ITEM,\n",
    "    rule(\n",
    "        COMMA,\n",
    "        ITEM\n",
    "    ).optional().repeatable()\n",
    ")\n",
    "\n",
    "RELOCATION = rule(\n",
    "    IS_READY,\n",
    "    rule(\n",
    "        COLON,\n",
    "        LOCATIONS\n",
    "    ).optional()\n",
    ").interpretation(\n",
    "    Relocation\n",
    ").interpretation(\n",
    "    Intro.relocation\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    RELOCATION,\n",
    "    'готов к переезду',\n",
    "    'не готова к переезду',\n",
    "    'готова к переезду: Россия, Украина, СНГ',\n",
    "    'хочу переехать: Франция',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Travel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "готова к командировкам\n",
      "──────────────────────\n",
      "не готов к редким командировкам\n",
      "   ────────────────────────────\n"
     ]
    }
   ],
   "source": [
    "TYPES = {\n",
    "    'готов к командировкам': True,\n",
    "    'готов к редким командировкам': True,\n",
    "    'не готов к командировкам': False\n",
    "}\n",
    "\n",
    "TRAVEL = morph_pipeline(TYPES).interpretation(\n",
    "    Intro.travel.normalized().custom(TYPES.get)\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    TRAVEL,\n",
    "    'готова к командировкам',\n",
    "    'не готов к редким командировкам',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Position"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(['Продажи',\n",
       "  'Административный персонал',\n",
       "  'Консультирование',\n",
       "  'Медицина, фармацевтика',\n",
       "  'Юристы',\n",
       "  'Автомобильный бизнес',\n",
       "  'Государственная служба, некоммерческие организации',\n",
       "  'Маркетинг, реклама, PR',\n",
       "  'Транспорт, логистика',\n",
       "  'Домашний персонал'],\n",
       " ['Риски: рыночные',\n",
       "  'Тренерский состав',\n",
       "  'Делопроизводство',\n",
       "  'Администратор баз данных',\n",
       "  'Планирование, Размещение рекламы',\n",
       "  'Охранник',\n",
       "  'Кредиты: розничные',\n",
       "  'Банкеты',\n",
       "  'Информационные технологии, Интернет, Мультимедиа',\n",
       "  'Электроэнергетика'])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# https://api.hh.ru/specializations\n",
    "\n",
    "SPECIALIZATIONS = set(load_lines('dicts/specialization.txt'))\n",
    "SUBSPECIALIZATIONS = set(load_lines('dicts/subspecialization.txt'))\n",
    "\n",
    "seed(10)\n",
    "sample(sorted(SPECIALIZATIONS), 10), sample(sorted(SUBSPECIALIZATIONS), 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Желаемая должность и зарплата\n",
      "Водитель\n",
      "Транспорт, логистика\n",
      "\n",
      "• Автоперевозки\n",
      "• Водитель\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Начинающий специалист\n",
      "Начало карьеры, студенты\n",
      "\n",
      "• Административный персонал\n",
      "• Продажи\n",
      "• Финансы, Банки, Инвестиции\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Администратор\n",
      "Продажи\n",
      "\n",
      "• Розничная торговля\n",
      "• Торговые сети\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Продавец-консультант\n",
      "Продажи\n",
      "\n",
      "• Продавец в магазине\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Организатор мероприятий\n",
      "Искусство, развлечения, масс-медиа\n",
      "\n",
      "• Прочее\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Продавец-консультант\n",
      "Продажи\n",
      "\n",
      "• Розничная торговля\n",
      "• Торговые сети\n",
      "• Продавец в магазине\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Домработница\n",
      "Домашний персонал\n",
      "\n",
      "• домработница/домработник, Горничная\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Бармен, бармен кассир.\n",
      "Начало карьеры, студенты\n",
      "\n",
      "• Туризм, Гостиницы, Рестораны\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Менеджер по управлению товарными запасами\n",
      "Транспорт, логистика\n",
      "\n",
      "• Складское хозяйство\n",
      "• Логистика\n",
      "• Закупки, Снабжение\n",
      "---\n",
      "Желаемая должность и зарплата\n",
      "Экспедитор\n",
      "Начало карьеры, студенты\n",
      "\n",
      "• Транспорт, Логистика\n",
      "---\n"
     ]
    }
   ],
   "source": [
    "TITLE = pipeline([\n",
    "    'Желаемая должность и зарплата'\n",
    "])\n",
    "\n",
    "DOT = eq('•')\n",
    "\n",
    "SUBTITLE = not_(DOT).repeatable().interpretation(\n",
    "    Intro.position\n",
    ")\n",
    "\n",
    "SPECIALIZATION = pipeline(SPECIALIZATIONS)\n",
    "\n",
    "SUBSPECIALIZATION = pipeline(SUBSPECIALIZATIONS)\n",
    "\n",
    "ITEM = rule(\n",
    "    DOT,\n",
    "    or_(\n",
    "        SPECIALIZATION,\n",
    "        SUBSPECIALIZATION\n",
    "    ).interpretation(\n",
    "        Intro.subspecializations\n",
    "    )\n",
    ")\n",
    "\n",
    "POSITION = rule(\n",
    "    TITLE,\n",
    "    SUBTITLE,\n",
    "    ITEM.repeatable()\n",
    ")\n",
    "\n",
    "\n",
    "TOKENIZER = MorphTokenizer().remove_types(EOL)\n",
    "\n",
    "\n",
    "parser = Parser(POSITION, tokenizer=TOKENIZER)\n",
    "seed(10)\n",
    "for text in sample(intros, 10):\n",
    "    for match in parser.findall(text):\n",
    "        start, stop = match.span\n",
    "        print(text[start:stop])\n",
    "        print('---')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Employment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Занятость: полная, частичная\n",
      "────────────────────────────\n",
      "Занятость: стажировка\n",
      "─────────────────────\n"
     ]
    }
   ],
   "source": [
    "TITLE = rule(\n",
    "    'Занятость', COLON\n",
    ")\n",
    "\n",
    "TYPES = {\n",
    "    'полная': 'full',\n",
    "    'полная занятость': 'full',\n",
    "    'частичная': 'part',\n",
    "    'частичная занятость': 'part',\n",
    "    'волонтерство': 'volunteer',\n",
    "    'стажировка': 'intern',\n",
    "    'проектная работа': 'project'\n",
    "    \n",
    "}\n",
    "\n",
    "TYPE = pipeline(TYPES).interpretation(\n",
    "    Intro.employment.normalized().custom(TYPES.get)\n",
    ")\n",
    "\n",
    "TYPES = rule(\n",
    "    TYPE,\n",
    "    rule(\n",
    "        COMMA,\n",
    "        TYPE\n",
    "    ).optional().repeatable()\n",
    ")\n",
    "\n",
    "EMPLOYMENT = rule(\n",
    "    TITLE,\n",
    "    TYPES\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    EMPLOYMENT,\n",
    "    'Занятость: полная, частичная',\n",
    "    'Занятость: стажировка',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Schedule"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "График работы: полный день, удаленная работа\n",
      "────────────────────────────────────────────\n",
      "График работы: стажировка\n",
      "─────────────────────────\n"
     ]
    }
   ],
   "source": [
    "TITLE = pipeline([\n",
    "    'График работы:'\n",
    "])\n",
    "\n",
    "TYPES = {\n",
    "    'полный день': 'full',\n",
    "    'сменный график': 'part',\n",
    "    'вахтовый метод': 'vahta',\n",
    "    'гибкий график': 'flex',\n",
    "    'удаленная работа': 'remote',\n",
    "    'стажировка': 'intern'\n",
    "}\n",
    "\n",
    "TYPE = morph_pipeline(TYPES).interpretation(\n",
    "    Intro.schedule.normalized().custom(TYPES.get)\n",
    ")\n",
    "\n",
    "TYPES = rule(\n",
    "    TYPE,\n",
    "    rule(\n",
    "        COMMA,\n",
    "        TYPE\n",
    "    ).optional().repeatable()\n",
    ")\n",
    "\n",
    "SCHEDULE = rule(\n",
    "    TITLE,\n",
    "    TYPES\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    SCHEDULE,\n",
    "    'График работы: полный день, удаленная работа',\n",
    "    'График работы: стажировка',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Commute"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Желательное время в пути до работы: не более часа\n",
      "─────────────────────────────────────────────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "─────────────────────────────────────────────────────\n"
     ]
    }
   ],
   "source": [
    "TITLE = pipeline([\n",
    "    'Желательное время в пути до работы:',\n",
    "])\n",
    "\n",
    "TYPES = {\n",
    "    'не более часа': '<1h',\n",
    "    'не имеет значения': 'any',\n",
    "    'не более полутора часов': '<1h30m'\n",
    "}\n",
    "\n",
    "TYPE = pipeline(TYPES).interpretation(\n",
    "    Intro.commute.normalized().custom(TYPES.get)\n",
    ")\n",
    "\n",
    "COMMUTE = rule(\n",
    "    TITLE,\n",
    "    TYPE\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    COMMUTE,\n",
    "    'Желательное время в пути до работы: не более часа',\n",
    "    'Желательное время в пути до работы: не имеет значения',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Money"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 500 руб.\n",
      "──────────\n",
      "1 000 000 грн.\n",
      "  ────────────\n",
      "5000 бел.руб.\n",
      "─────────────\n",
      "20 000 KGS\n",
      "──────────\n"
     ]
    }
   ],
   "source": [
    "Money = fact(\n",
    "    'Money',\n",
    "    ['amount', 'currency']\n",
    ")\n",
    "\n",
    "\n",
    "CURRENCIES = {\n",
    "    'руб.': 'RUB',\n",
    "    'грн.': 'GRN',\n",
    "    'бел. руб.': 'BEL',\n",
    "    'RUB': 'RUB',\n",
    "    'EUR': 'EUR',\n",
    "    'KZT': 'KZT',\n",
    "    'USD': 'USD',\n",
    "    'KGS': 'KGS'\n",
    "}\n",
    "\n",
    "CURRENCY = pipeline(CURRENCIES).interpretation(\n",
    "    Money.currency.normalized().custom(CURRENCIES.get)\n",
    ")\n",
    "\n",
    "\n",
    "def normalize_amount(value):\n",
    "    return int(value.replace(' ', ''))\n",
    "\n",
    "\n",
    "AMOUNT = or_(\n",
    "    rule(INT),\n",
    "    rule(INT, INT),\n",
    ").interpretation(\n",
    "    Money.amount.custom(normalize_amount)\n",
    ")\n",
    "\n",
    "MONEY = rule(\n",
    "    AMOUNT,\n",
    "    CURRENCY\n",
    ").interpretation(\n",
    "    Money\n",
    ").interpretation(\n",
    "    Intro.salary\n",
    ")\n",
    "\n",
    "\n",
    "show_matches(\n",
    "    MONEY,\n",
    "    '1 500 руб.',\n",
    "    '1 000 000 грн.',\n",
    "    '5000 бел.руб.',\n",
    "    '20 000 KGS',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Intro"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Мужчина, 24 года, родился 30 ноября 1991\n",
      "───────  ──               ── ────── ────\n",
      "Проживает: Москва, м. Новогиреево\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готов к переезду, не готов к командировкам\n",
      "───────────────────  ────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Водитель\n",
      "────────\n",
      "Транспорт, логистика\n",
      "────────────────────\n",
      "• Автоперевозки\n",
      "  ─────────────\n",
      "• Водитель\n",
      "  ────────\n",
      "Занятость: полная занятость\n",
      "           ────────────────\n",
      "График работы: полный день\n",
      "               ───────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "45 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 2 года 5 месяцев\n",
      "Май 2015 —\n",
      "Апрель 2016\n",
      "1 год\n",
      "ООО Панавто, г. Москва.\n",
      "Диспетчер\n",
      "Панавто- официальный представитель Mercedes-Benz в Москве.3 месяца \n",
      "работал\n",
      "водителем-перегонщиком, основная деятельность перемещение автомобилей.\n",
      " Далее стал\n",
      "диспетчером, к основным обязанностям перемещения добавилс\n",
      "{\n",
      "  \"gender\": \"male\",\n",
      "  \"age\": 24,\n",
      "  \"birth\": {\n",
      "    \"year\": 1991,\n",
      "    \"month\": 11,\n",
      "    \"day\": 30\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Водитель Транспорт, логистика\",\n",
      "  \"subspecializations\": [\n",
      "    \"Автоперевозки\",\n",
      "    \"Водитель\"\n",
      "  ],\n",
      "  \"employment\": \"full\",\n",
      "  \"schedule\": \"full\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 45000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Женщина, 19 лет, родилась 30 мая 1997\n",
      "───────  ──               ── ─── ────\n",
      "Проживает: Тула\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готова к переезду, не готова к командировкам\n",
      "────────────────────  ─────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Начинающий специалист\n",
      "─────────────────────\n",
      "Начало карьеры, студенты\n",
      "────────────────────────\n",
      "• Административный персонал\n",
      "  ─────────────────────────\n",
      "• Продажи\n",
      "  ───────\n",
      "• Финансы, Банки, Инвестиции\n",
      "  ──────────────────────────\n",
      "Занятость: частичная занятость, проектная работа\n",
      "                                ────────────────\n",
      "График работы: гибкий график\n",
      "               ─────────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "13 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Образование\n",
      "Высшее\n",
      "2019 Тульский филиал РАНХиГС\n",
      "ГМУ, ГМУ\n",
      "Ключевые навыки\n",
      "Знание языков Русский — родной\n",
      "Английский — базовые знания\n",
      "Немецкий — базовые знания\n",
      "Резюме обновлено 25 августа 2016 в 18:15\n",
      "[image: image0.png]\n",
      "{\n",
      "  \"gender\": \"female\",\n",
      "  \"age\": 19,\n",
      "  \"birth\": {\n",
      "    \"year\": 1997,\n",
      "    \"month\": 5,\n",
      "    \"day\": 30\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Начинающий специалист Начало карьеры, студенты\",\n",
      "  \"subspecializations\": [\n",
      "    \"Административный персонал\",\n",
      "    \"Продажи\",\n",
      "    \"Финансы, Банки, Инвестиции\"\n",
      "  ],\n",
      "  \"employment\": \"project\",\n",
      "  \"schedule\": \"flex\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 13000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Женщина, 58 лет, родилась 5 января 1958\n",
      "───────  ──               ─ ────── ────\n",
      "Проживает: Липецк\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готова к переезду, не готова к командировкам\n",
      "────────────────────  ─────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Администратор\n",
      "─────────────\n",
      "Продажи\n",
      "───────\n",
      "• Розничная торговля\n",
      "  ──────────────────\n",
      "• Торговые сети\n",
      "  ─────────────\n",
      "Занятость: полная занятость\n",
      "           ────────────────\n",
      "График работы: гибкий график\n",
      "               ─────────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "20 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 35 лет 9 месяцев\n",
      "Октябрь 1982 —\n",
      "Март 2016\n",
      "33 года 6 месяцев\n",
      "НЛМК\n",
      "Россия, nlmk.com/ru\n",
      "Дозировщик\n",
      "Следить за подачей углей из дозатора.\n",
      "Февраль 1980 —\n",
      "Апрель 1982\n",
      "2 года 3 месяца\n",
      "Продуктовый магазин\n",
      "Старший продавец\n",
      "Следить за персоналом.\n",
      "Образование\n",
      "Среднее специальное\n",
      "1976 Чебоксарский планово-эконо\n",
      "{\n",
      "  \"gender\": \"female\",\n",
      "  \"age\": 58,\n",
      "  \"birth\": {\n",
      "    \"year\": 1958,\n",
      "    \"month\": 1,\n",
      "    \"day\": 5\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Администратор Продажи\",\n",
      "  \"subspecializations\": [\n",
      "    \"Розничная торговля\",\n",
      "    \"Торговые сети\"\n",
      "  ],\n",
      "  \"employment\": \"full\",\n",
      "  \"schedule\": \"flex\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 20000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Мужчина, 21 год, родился 18 октября 1994\n",
      "───────  ──              ── ─────── ────\n",
      "Проживает: Зеленоград\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готов к переезду, не готов к командировкам\n",
      "───────────────────  ────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Продавец-консультант\n",
      "────────────────────\n",
      "Продажи\n",
      "───────\n",
      "• Продавец в магазине\n",
      "  ───────────────────\n",
      "Занятость: полная занятость\n",
      "           ────────────────\n",
      "График работы: полный день\n",
      "               ───────────\n",
      "Желательное время в пути до работы: не более часа\n",
      "                                    ─────────────\n",
      "32 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 1 год 8 месяцев\n",
      "Январь 2016 —\n",
      "настоящее время\n",
      "9 месяцев\n",
      "ИП Медведева О.В.\n",
      "Зеленоград\n",
      "Администратор\n",
      "Общение с клиентами, работа программе 1С, с деньгами и документацией.\n",
      "Февраль 2013 —\n",
      "Декабрь 2013\n",
      "11 месяцев\n",
      "ГБОУ г.Москвы Зеленоградский ДТДиМ\n",
      "Работник ТРЗ 4 разряда\n",
      "Обслуживание оборудования. Монтаж, демонтаж деко\n",
      "{\n",
      "  \"gender\": \"male\",\n",
      "  \"age\": 21,\n",
      "  \"birth\": {\n",
      "    \"year\": 1994,\n",
      "    \"month\": 10,\n",
      "    \"day\": 18\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Продавец-консультант Продажи\",\n",
      "  \"subspecializations\": [\n",
      "    \"Продавец в магазине\"\n",
      "  ],\n",
      "  \"employment\": \"full\",\n",
      "  \"schedule\": \"full\",\n",
      "  \"commute\": \"<1h\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 32000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Мужчина, 25 лет, родился 15 ноября 1990\n",
      "───────  ──              ── ────── ────\n",
      "Проживает: Новосибирск, м. Золотая нива\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готов к переезду, готов к командировкам\n",
      "───────────────────  ─────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Организатор мероприятий\n",
      "───────────────────────\n",
      "Искусство, развлечения, масс-медиа\n",
      "──────────────────────────────────\n",
      "• Прочее\n",
      "  ──────\n",
      "Занятость: полная занятость, частичная занятость\n",
      "                             ───────────────────\n",
      "График работы: полный день, сменный график, гибкий график\n",
      "                                            ─────────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "23 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 3 года 7 месяцев\n",
      "Август 2015 —\n",
      "Декабрь 2015\n",
      "5 месяцев\n",
      "Театральное агентство «Премьера»\n",
      "Москва\n",
      "Помощник администратора\n",
      "Организация и проведение культурно-массовых мероприятий в сфере \n",
      "театрально-концертного\n",
      "бизнеса. Реализация биле\n",
      "{\n",
      "  \"gender\": \"male\",\n",
      "  \"age\": 25,\n",
      "  \"birth\": {\n",
      "    \"year\": 1990,\n",
      "    \"month\": 11,\n",
      "    \"day\": 15\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": true,\n",
      "  \"position\": \"Организатор мероприятий Искусство, развлечения, масс-медиа\",\n",
      "  \"subspecializations\": [\n",
      "    \"Прочее\"\n",
      "  ],\n",
      "  \"employment\": \"part\",\n",
      "  \"schedule\": \"flex\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 23000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Женщина, 18 лет, родилась 26 ноября 1997\n",
      "───────  ──               ── ────── ────\n",
      "Проживает: Тамбов\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готова к переезду, не готова к командировкам\n",
      "────────────────────  ─────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Продавец-консультант\n",
      "────────────────────\n",
      "Продажи\n",
      "───────\n",
      "• Розничная торговля\n",
      "  ──────────────────\n",
      "• Торговые сети\n",
      "  ─────────────\n",
      "• Продавец в магазине\n",
      "  ───────────────────\n",
      "Занятость: полная занятость\n",
      "           ────────────────\n",
      "График работы: полный день, сменный график\n",
      "                            ──────────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "15 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 5 месяцев\n",
      "Май 2015 —\n",
      "Сентябрь 2015\n",
      "5 месяцев\n",
      "ИП Каскад\n",
      "Тамбовская область\n",
      "Продавец-кассир\n",
      "Продавец ответственный и целеустремленный, с опытом активного \n",
      "обслуживания\n",
      "покупателей в соответствии с корпоративными стандартами, грамотной \n",
      "речью, аккуратный и\n",
      "нацеленн\n",
      "{\n",
      "  \"gender\": \"female\",\n",
      "  \"age\": 18,\n",
      "  \"birth\": {\n",
      "    \"year\": 1997,\n",
      "    \"month\": 11,\n",
      "    \"day\": 26\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Продавец-консультант Продажи\",\n",
      "  \"subspecializations\": [\n",
      "    \"Розничная торговля\",\n",
      "    \"Торговые сети\",\n",
      "    \"Продавец в магазине\"\n",
      "  ],\n",
      "  \"employment\": \"full\",\n",
      "  \"schedule\": \"part\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 15000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Женщина, 27 лет, родилась 5 сентября 1988\n",
      "───────  ──               ─ ──────── ────\n",
      "Проживает: Москва\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готова к переезду, не готова к командировкам\n",
      "────────────────────  ─────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Домработница\n",
      "────────────\n",
      "Домашний персонал\n",
      "─────────────────\n",
      "• домработница/домработник, Горничная\n",
      "  ───────────────────────────────────\n",
      "Занятость: частичная занятость\n",
      "           ───────────────────\n",
      "График работы: полный день\n",
      "               ───────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "3 500\n",
      "─────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 4 года 7 месяцев\n",
      "Сентябрь 2014 —\n",
      "Март 2015\n",
      "7 месяцев\n",
      "Частное лицо\n",
      "Домраблтница\n",
      "сухая и влажная уборка стирка, глажка, а также мойку окон\n",
      "Без вредных привычек, ответственная, добросовестная.\n",
      "Строго без интима!!!Производила сухую и влажную уборку, стирку, глажку\n",
      "Без вредных привычек, ответственн\n",
      "{\n",
      "  \"gender\": \"female\",\n",
      "  \"age\": 27,\n",
      "  \"birth\": {\n",
      "    \"year\": 1988,\n",
      "    \"month\": 9,\n",
      "    \"day\": 5\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Домработница Домашний персонал\",\n",
      "  \"subspecializations\": [\n",
      "    \"домработница/домработник, Горничная\"\n",
      "  ],\n",
      "  \"employment\": \"part\",\n",
      "  \"schedule\": \"full\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 3500,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Мужчина, 20 лет, родился 24 июля 1996\n",
      "───────  ──              ── ──── ────\n",
      "Проживает: Москва, м. Сухаревская\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готов к переезду, не готов к командировкам\n",
      "───────────────────  ────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Бармен, бармен кассир.\n",
      "──────────────────────\n",
      "Начало карьеры, студенты\n",
      "────────────────────────\n",
      "• Туризм, Гостиницы, Рестораны\n",
      "  ────────────────────────────\n",
      "Занятость: полная занятость, частичная занятость\n",
      "                             ───────────────────\n",
      "График работы: полный день, сменный график\n",
      "                            ──────────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "45 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Образование\n",
      "Среднее специальное\n",
      "2015 ГБОУ СПО МКБТ №6\n",
      "Финансы, Финансист\n",
      "Ключевые навыки\n",
      "Знание языков Русский — родной\n",
      "Английский — базовые знания\n",
      "Навыки  Баристика      Барное ремесло      Кассовые операции      \n",
      "Работа в команде \n",
      " R-Keeper      Акт\n",
      "{\n",
      "  \"gender\": \"male\",\n",
      "  \"age\": 20,\n",
      "  \"birth\": {\n",
      "    \"year\": 1996,\n",
      "    \"month\": 7,\n",
      "    \"day\": 24\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Бармен, бармен кассир. Начало карьеры, студенты\",\n",
      "  \"subspecializations\": [\n",
      "    \"Туризм, Гостиницы, Рестораны\"\n",
      "  ],\n",
      "  \"employment\": \"part\",\n",
      "  \"schedule\": \"part\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 45000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Мужчина, 38 лет, родился 24 мая 1978\n",
      "───────  ──              ── ─── ────\n",
      "Проживает: Энгельс\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готов к переезду, не готов к командировкам\n",
      "───────────────────  ────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Менеджер по управлению товарными запасами\n",
      "─────────────────────────────────────────\n",
      "Транспорт, логистика\n",
      "────────────────────\n",
      "• Складское хозяйство\n",
      "  ───────────────────\n",
      "• Логистика\n",
      "  ─────────\n",
      "• Закупки, Снабжение\n",
      "  ──────────────────\n",
      "Занятость: полная занятость\n",
      "           ────────────────\n",
      "График работы: полный день\n",
      "               ───────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "25 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Опыт работы — 11 лет 6 месяцев\n",
      "Август 2015 —\n",
      "Апрель 2016\n",
      "9 месяцев\n",
      "ооо рус-кон-с\n",
      "Энгельс\n",
      "Стропальщик\n",
      "Приемка товара,сортировка,складирование с последующей продажей.\n",
      "Октябрь 2014 —\n",
      "Июль 2015\n",
      "10 месяцев\n",
      "завод ЖБК-3\n",
      "Энгельс, www.3r.ru\n",
      "Стропальщик\n",
      "Приемка продукции,\n",
      "{\n",
      "  \"gender\": \"male\",\n",
      "  \"age\": 38,\n",
      "  \"birth\": {\n",
      "    \"year\": 1978,\n",
      "    \"month\": 5,\n",
      "    \"day\": 24\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Менеджер по управлению товарными запасами Транспорт, логистика\",\n",
      "  \"subspecializations\": [\n",
      "    \"Складское хозяйство\",\n",
      "    \"Логистика\",\n",
      "    \"Закупки, Снабжение\"\n",
      "  ],\n",
      "  \"employment\": \"full\",\n",
      "  \"schedule\": \"full\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 25000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n",
      "Мужчина, 21 год, родился 8 июня 1995\n",
      "───────  ──              ─ ──── ────\n",
      "Проживает: Казань, м. Проспект Победы\n",
      "Гражданство: Россия, есть разрешение на работу: Россия\n",
      "             ──────                             ──────\n",
      "Не готов к переезду, не готов к командировкам\n",
      "───────────────────  ────────────────────────\n",
      "Желаемая должность и зарплата\n",
      "Экспедитор\n",
      "──────────\n",
      "Начало карьеры, студенты\n",
      "────────────────────────\n",
      "• Транспорт, Логистика\n",
      "  ────────────────────\n",
      "Занятость: полная занятость\n",
      "           ────────────────\n",
      "График работы: полный день\n",
      "               ───────────\n",
      "Желательное время в пути до работы: не имеет значения\n",
      "                                    ─────────────────\n",
      "25 000\n",
      "──────\n",
      "руб.\n",
      "────\n",
      "Образование\n",
      "Среднее специальное\n",
      "2014 плнхп 40\n",
      "столяр, резба по дереву\n",
      "Ключевые навыки\n",
      "Знание языков Русский — родной\n",
      "Дополнительная информация\n",
      "Обо мне Работал  не офицыально экспедитором на продуктах питания !\n",
      "Резюме обновлено 9 марта 2016 в 11:48\n",
      "[image: image0.png]\n",
      "{\n",
      "  \"gender\": \"male\",\n",
      "  \"age\": 21,\n",
      "  \"birth\": {\n",
      "    \"year\": 1995,\n",
      "    \"month\": 6,\n",
      "    \"day\": 8\n",
      "  },\n",
      "  \"citizenship\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"permission\": [\n",
      "    \"Россия\"\n",
      "  ],\n",
      "  \"relocation\": {\n",
      "    \"ready\": false,\n",
      "    \"where\": []\n",
      "  },\n",
      "  \"travel\": false,\n",
      "  \"position\": \"Экспедитор Начало карьеры, студенты\",\n",
      "  \"subspecializations\": [\n",
      "    \"Транспорт, Логистика\"\n",
      "  ],\n",
      "  \"employment\": \"full\",\n",
      "  \"schedule\": \"full\",\n",
      "  \"commute\": \"any\",\n",
      "  \"salary\": {\n",
      "    \"amount\": 25000,\n",
      "    \"currency\": \"RUB\"\n",
      "  }\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "INTRO = rule(\n",
    "    SOCDEM,\n",
    "    LIVES_AT,\n",
    "    CITIZENSHIP, COMMA, PERMISSION,\n",
    "    RELOCATION, COMMA, TRAVEL,\n",
    "    POSITION,\n",
    "    EMPLOYMENT,\n",
    "    SCHEDULE,\n",
    "    COMMUTE,\n",
    "    MONEY\n",
    ").interpretation(\n",
    "    Intro\n",
    ")\n",
    "\n",
    "\n",
    "parser = Parser(INTRO, tokenizer=TOKENIZER)\n",
    "seed(10)\n",
    "for text in sample(intros, 10):\n",
    "    matches = list(parser.findall(text))\n",
    "    if matches:\n",
    "        match = matches[0]\n",
    "        fact = match.fact\n",
    "        show_markup(text, fact.spans)\n",
    "        show_json(fact.as_json)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
